package com.hup.utils.swing;

import lombok.extern.log4j.Log4j2;
import sun.awt.SunToolkit;
import sun.misc.SoftCache;

import javax.swing.ImageIcon;
import java.awt.Image;
import java.awt.Toolkit;
import java.lang.reflect.Field;
import java.net.URL;

/**
 * @author hugan
 * @date 2020/1/4
 */
@Log4j2
public abstract class IconUtil {

    /**
     * @param imgPath 如:[/img/cursor.gif]
     * @apiNote 支持jar和war;不支持外部文件
     */
    public static ImageIcon getIcon(String imgPath, String desc) {
        URL url = IconUtil.class.getResource(imgPath);
        if (url == null) {
            throw new IllegalArgumentException("[" + desc + "]加载异常:[" + imgPath + "]");
        }
        return checkImage(new ImageIcon(url), imgPath, desc);
    }

    private static ImageIcon checkImage(ImageIcon imageIcon, String imgPath, String desc) {
        if (imageIcon.getIconWidth() == -1 || imageIcon.getIconHeight() == -1) {
            throw new IllegalArgumentException("[" + desc + "]加载异常:[" + imgPath + "]");
        }
        return imageIcon;
    }

    /**
     * 获取[外部]图像
     *
     * @return 如果图像(路径, 文件)已经被加载过, 则返回的是缓存中的图像数据(看源码), 非最新的图像数据
     */
    public static Image getFileImage(String imgPath, String desc) {
        ImageIcon imageIcon = new ImageIcon(imgPath, desc);
        return checkImage(imageIcon, imgPath, desc).getImage();
    }

    /**
     * 获取无缓存的[外部]图像,适用于测试或文件会刷新的情况
     * @apiNote 基于反射实现,非平台通用的
     */
    public static Image getFileImageNoCache(String imgPath, String desc) {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        if (toolkit instanceof SunToolkit) {
            //清除缓存:通过反射
            SunToolkit sunToolkit = (SunToolkit) toolkit;
            try {
                Field field = SunToolkit.class.getDeclaredField("fileImgCache");
                field.setAccessible(true);
                SoftCache fileImgCache = (SoftCache) field.get(sunToolkit);
                boolean hadCache = fileImgCache.containsKey(imgPath);
                if (hadCache) {
                    Image removed = (Image) fileImgCache.remove(imgPath);
                    removed.flush();
                    log.debug("成功清除缓存imgPath={}",imgPath);
                }
            } catch (Exception e) {
                log.error("清除缓存异常={}, {}", desc, imgPath);
            }
        } else {
            log.warn("Toolkit不支持获取无缓存图像,加载的图像可能是缓存数据:{}, {}", desc, imgPath);
        }
        return getFileImage(imgPath, desc);
    }

}
